
SemReturnValueA semClearMessageA(ErtmsMessageA *pMessage)
{
	SemErrorCodeA errorCode = SEM_OK_A;
	SemReturnValueA rv = SEM_NO_ERROR_A;

	if (pMessage == NULL) {
		errorCode = SEM_CLEAR_MESSAGE_A;
	} else {
		memset(pMessage, 0, sizeof(*pMessage));
	}
	
	if (errorCode != SEM_OK_A) {
		semSetErrorCodeA(errorCode);
		rv = SEM_CLEAR_MESSAGE_ERROR_A;
	}

	return rv;
}

SemReturnValueA semSerializeA(CONST ErtmsMessageA *pMessage, UINT8_t *pBuffer, UINT32_t *pnSize)
{
	SemBufferA bitBuffer;
	SemErrorCodeA errorCode = SEM_OK_A;
	SemReturnValueA rv = SEM_NO_ERROR_A;

	if ((pMessage == NULL) || (pBuffer == NULL) || (pnSize == NULL)) {
		rv = SEM_SERIALIZE_ERROR_A;
	} else {
		semInitBufferA(&bitBuffer, pBuffer, pnSize);

		errorCode = ertmsMsgComposeA(pMessage, &bitBuffer);

		if (errorCode == SEM_OK_A) {
			*pnSize = ((bitBuffer.nBitCount - 1u) / 8u) + 1u;
		}
	}
	
	if (errorCode != SEM_OK_A) {
		semSetErrorCodeA(errorCode);
		rv = SEM_SERIALIZE_ERROR_A;
	}
	
	return rv;
}

SemReturnValueA semDeserializeA(UINT8_t *pBuffer, UINT32_t *pnLength, ErtmsMessageA *pMessage)
{
	SemBufferA bitBuffer;
	SemErrorCodeA errorCode = SEM_OK_A;
	SemReturnValueA rv = SEM_NO_ERROR_A;

	if ((pMessage == NULL) || (pBuffer == NULL) || (pnLength == NULL)) {
		errorCode = SEM_DESERIALIZE_A;
	} else {
		semInitBufferA(&bitBuffer, pBuffer, pnLength);

		errorCode = ertmsMsgResolveA(pMessage, &bitBuffer);

		if (errorCode == SEM_OK_A) {
			*pnLength = ((bitBuffer.nBitCount - 1u) / 8u) + 1u;
		}
	}
	
	if (errorCode != SEM_OK_A) {
		semSetErrorCodeA(errorCode);
		rv = SEM_DESERIALIZE_ERROR_A;
	}

	return rv;
}

SemReturnValueA semGetLengthA(CONST ErtmsMessageA *pMessage, UINT32_t *pnLength)
{
	UINT8_t tmp[600];
	SemErrorCodeA errorCode = SEM_OK_A;
	SemReturnValueA rv = SEM_NO_ERROR_A;

	if ((pMessage == NULL) || (pnLength == NULL)) {
		errorCode = SEM_GET_LENGTH_A;
	} else {
		/* Simply build the message and throw away the data to measure the length */
		*pnLength = sizeof(tmp);
		rv = semSerializeA(pMessage, tmp, pnLength);
	}
	
	if (errorCode != SEM_OK_A) {
		semSetErrorCodeA(errorCode);
		rv = SEM_GET_LENGTH_ERROR_A;
	}

	return rv;
}

CONST char* semGetErrorStringA(void)
{	
	CONST char* returnString;
	
	if (((size_t)semErrorCodeA >= (sizeof(errorCodeList)/sizeof(ErrorCodeListA))) || (errorCodeList[semErrorCodeA].errorCode != semErrorCodeA)) {
		returnString = errorCodeList[SEM_UNEXPECTED_INDEX_A].text;
	} else {
		returnString = errorCodeList[semErrorCodeA].text;
	}

	return returnString;
}

void semSetErrorCodeA(CONST SemErrorCodeA errorCode)
{
	semErrorCodeA = errorCode;
}

UINT32_t semGetNidCA(UINT32_t nNID_LRBG)
{
	return (nNID_LRBG >> SEM_SIZE_NID_ID_A);
}

UINT32_t semGetNidBgA(UINT32_t nNID_LRBG)
{
	return (nNID_LRBG & SEM_MASK_NID_ID_A);
}

UINT32_t semGetNID_LRBGA(UINT32_t nNID_C, UINT32_t nNID_BG)
{
	return ((nNID_C << SEM_SIZE_NID_ID_A) | nNID_BG);
}
